/**
 * 
 */
package zeroj.web.format;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import zeroj.web.annotations.Form;
import zeroj.web.format.annotations.FormatCharacter;
import zeroj.web.format.annotations.FormatFloat;
import zeroj.web.format.annotations.FormatInteger;
import zeroj.web.format.annotations.FormatLong;
import zeroj.web.format.annotations.FormatString;
import zeroj.web.format.impl.CharFormater;
import zeroj.web.format.impl.FloatFormater;
import zeroj.web.format.impl.IntegerFormater;
import zeroj.web.format.impl.LongFormater;
import zeroj.web.format.impl.StringFormater;

/**
 * @author LYL(lylsir at gmail dot com)
 *
 */
public final class FormatHelper {

	public static List<Format> parseFormats(Class<?> clz) {
		
		List<Format> formats = new ArrayList<Format>();
		parseFormats(formats, null, clz);
		return formats;
	}
	private static void parseFormats(List<Format> formats, String baseName, Class<?> clz) {
		
		for(Field filed : clz.getFields())
			parseFieldFormats(formats, null, filed);
		for(Method method : clz.getMethods())
			parseMethodFormats(formats, null, method);
	}
	private static void parseFieldFormats(List<Format> formats, String baseName, Field field) {
		
		String name = field.getName();
		if(baseName != null)
			name = baseName + "." + name;
		Field[] fields = field.getClass().getFields();
		if(fields.length > 0) {
			for(Field f : fields) {
				if(field.isAnnotationPresent(Form.class))
					parseFormats(formats, name, f.getClass());
			}
		} else {
			IFormater formater = getFormater(field.getClass(), field.getAnnotations(), baseName != null);
			if(formater == null)
				return;
			formats.add(new Format(name, formater));
		}

	}
	private static void parseMethodFormats(List<Format> formats, String baseName, Method method) {
		
		Class<?> clz[] = method.getParameterTypes();
		if(clz.length != 1)
			return;
		IFormater formater = getFormater(clz[0], method.getAnnotations(), baseName != null);
		if(formater == null)
			return;
		Character c = Character.toLowerCase(method.getName().charAt(3));
		String name = c + method.getName().substring(4);
		if(baseName != null)
			name = baseName + "." + name;
		formats.add(new Format(name, formater));
	}
	private static IFormater getFormater(Class<?> clz, Annotation[] annotations, boolean addDefault) {
		
		for(Annotation anno : annotations) {
			
			Class<?> annoClass = anno.getClass();
			if(FormatCharacter.class == annoClass)
				return new CharFormater(((FormatCharacter)anno).defaultValue());
			else if(FormatFloat.class == annoClass) {
				FormatFloat ff = (FormatFloat)anno;
				return new FloatFormater(ff.defaultValue());
			} else if(FormatInteger.class == annoClass) {
				FormatInteger fi = (FormatInteger)anno;
				return new IntegerFormater(fi.defaultValue());
			} else if(FormatLong.class == annoClass) {
				FormatLong fl = (FormatLong)anno;
				return new LongFormater(fl.defaultValue());
			} else if(FormatString.class == annoClass) {
				FormatString fs = (FormatString)anno;
				return new StringFormater(fs.trim(), fs.lower(), fs.defaultValue());
			}
		}
		return addDefault ? defaultFormater(clz) : null;
	}
	
	private static IFormater defaultFormater(Class<?> clz) {
		
		if(clz == int.class || clz == Integer.class)
			return IntegerFormater.getDefaultInstance();
		else if(clz == long.class || clz == Long.class)
			return LongFormater.getDefaultInstance();
		else if(clz == float.class || clz == Float.class)
			return FloatFormater.getDefaultInstance();
		else if(clz == String.class)
			return StringFormater.getDefaultInstance();
		return null;
	}
	
}
